import React, { Suspense, ComponentType, LazyExoticComponent } from 'react';
import { Spin } from 'antd';

// 加载状态组件
export const PageLoading: React.FC = () => (
  <div style={{
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    height: '100vh',
    backgroundColor: '#f5f5f5'
  }}>
    <Spin size="large" tip="加载中..." />
  </div>
);

// 卡片加载状态
export const CardLoading: React.FC = () => (
  <div style={{
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    padding: '50px',
    backgroundColor: '#fff',
    borderRadius: '8px',
    boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
  }}>
    <Spin tip="加载中..." />
  </div>
);

// 表格加载状态
export const TableLoading: React.FC = () => (
  <div style={{
    display: 'flex',
    justifyContent: 'center',
    alignItems: 'center',
    padding: '100px',
    backgroundColor: '#fff'
  }}>
    <Spin tip="数据加载中..." />
  </div>
);

// 骨架屏组件
export const SkeletonLoader: React.FC<{
  type?: 'page' | 'card' | 'table' | 'form';
  rows?: number;
}> = ({ type = 'page', rows = 3 }) => {
  const renderSkeleton = () => {
    switch (type) {
      case 'page':
        return (
          <div style={{ padding: '24px' }}>
            <div style={{ height: '32px', backgroundColor: '#f0f0f0', marginBottom: '24px', borderRadius: '4px' }} />
            {Array.from({ length: rows }).map((_, i) => (
              <div key={i} style={{ marginBottom: '16px' }}>
                <div style={{ height: '20px', backgroundColor: '#f0f0f0', borderRadius: '4px', marginBottom: '8px' }} />
                <div style={{ height: '16px', backgroundColor: '#f0f0f0', borderRadius: '4px', width: '60%' }} />
              </div>
            ))}
          </div>
        );

      case 'card':
        return (
          <div style={{ padding: '16px' }}>
            <div style={{ height: '24px', backgroundColor: '#f0f0f0', marginBottom: '16px', borderRadius: '4px' }} />
            {Array.from({ length: rows }).map((_, i) => (
              <div key={i} style={{ marginBottom: '12px' }}>
                <div style={{ height: '16px', backgroundColor: '#f0f0f0', borderRadius: '4px', marginBottom: '8px' }} />
                <div style={{ height: '12px', backgroundColor: '#f0f0f0', borderRadius: '4px', width: '80%' }} />
              </div>
            ))}
          </div>
        );

      case 'table':
        return (
          <div style={{ padding: '16px' }}>
            <div style={{ display: 'flex', marginBottom: '16px', gap: '16px' }}>
              <div style={{ height: '32px', backgroundColor: '#f0f0f0', borderRadius: '4px', flex: 1 }} />
              <div style={{ height: '32px', backgroundColor: '#f0f0f0', borderRadius: '4px', width: '100px' }} />
            </div>
            {Array.from({ length: rows }).map((_, i) => (
              <div key={i} style={{ display: 'flex', marginBottom: '12px', gap: '16px' }}>
                <div style={{ height: '40px', backgroundColor: '#f0f0f0', borderRadius: '4px', flex: 1 }} />
                <div style={{ height: '40px', backgroundColor: '#f0f0f0', borderRadius: '4px', flex: 1 }} />
                <div style={{ height: '40px', backgroundColor: '#f0f0f0', borderRadius: '4px', flex: 1 }} />
              </div>
            ))}
          </div>
        );

      case 'form':
        return (
          <div style={{ padding: '16px' }}>
            {Array.from({ length: rows }).map((_, i) => (
              <div key={i} style={{ marginBottom: '24px' }}>
                <div style={{ height: '16px', backgroundColor: '#f0f0f0', borderRadius: '4px', marginBottom: '8px', width: '80px' }} />
                <div style={{ height: '40px', backgroundColor: '#f0f0f0', borderRadius: '4px' }} />
              </div>
            ))}
            <div style={{ display: 'flex', gap: '16px' }}>
              <div style={{ height: '40px', backgroundColor: '#f0f0f0', borderRadius: '4px', width: '100px' }} />
              <div style={{ height: '40px', backgroundColor: '#f0f0f0', borderRadius: '4px', width: '100px' }} />
            </div>
          </div>
        );

      default:
        return <PageLoading />;
    }
  };

  return <div style={{ backgroundColor: '#fff', borderRadius: '8px' }}>{renderSkeleton()}</div>;
};

// 创建带加载状态的懒加载组件
export function createLazyComponent<T extends ComponentType<any>>(
  importFn: () => Promise<{ default: T }>,
  fallback?: React.ReactNode,
  errorFallback?: React.ReactNode
): LazyExoticComponent<T> {
  const LazyComponent = React.lazy(importFn);

  const WrappedComponent: React.FC = (props) => (
    <Suspense fallback={fallback || <PageLoading />}>
      <ErrorBoundary fallback={errorFallback || <div>加载失败</div>}>
        <LazyComponent {...props} />
      </ErrorBoundary>
    </Suspense>
  );

  return React.memo(WrappedComponent) as LazyExoticComponent<T>;
}

// 错误边界组件
class ErrorBoundary extends React.Component<
  { children: React.ReactNode; fallback?: React.ReactNode },
  { hasError: boolean }
> {
  constructor(props: { children: React.ReactNode; fallback?: React.ReactNode }) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(): { hasError: boolean } {
    return { hasError: true };
  }

  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    console.error('Lazy loading error:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return this.props.fallback || <div>组件加载失败</div>;
    }

    return this.props.children;
  }
}

// 路由级懒加载
export function lazyRoute<T extends ComponentType<any>>(
  importFn: () => Promise<{ default: T }>
): LazyExoticComponent<T> {
  return createLazyComponent(
    importFn,
    <PageLoading />,
    <div style={{ textAlign: 'center', padding: '50px' }}>
      <h3>页面加载失败</h3>
      <button onClick={() => window.location.reload()}>重新加载</button>
    </div>
  );
}

// 组件级懒加载
export function lazyComponent<T extends ComponentType<any>>(
  importFn: () => Promise<{ default: T }>,
  type: 'card' | 'table' | 'form' = 'card'
): LazyExoticComponent<T> {
  const fallback = {
    card: <CardLoading />,
    table: <TableLoading />,
    form: <SkeletonLoader type="form" />
  }[type];

  return createLazyComponent(importFn, fallback);
}

// 预加载工具
export class PreloadManager {
  private preloadedComponents = new Set<string>();

  async preload<T>(componentName: string, importFn: () => Promise<{ default: T }>): Promise<void> {
    if (this.preloadedComponents.has(componentName)) {
      return;
    }

    try {
      await importFn();
      this.preloadedComponents.add(componentName);
    } catch (error) {
      console.error(`Failed to preload component ${componentName}:`, error);
    }
  }

  // 在空闲时预加载
  preloadOnIdle<T>(componentName: string, importFn: () => Promise<{ default: T }>): void {
    if (typeof window === 'undefined' || !('requestIdleCallback' in window)) {
      return;
    }

    window.requestIdleCallback(() => {
      this.preload(componentName, importFn);
    });
  }

  // 在用户交互时预加载
  preloadOnInteraction<T>(
    componentName: string,
    importFn: () => Promise<{ default: T }>,
    triggerElement?: HTMLElement
  ): void {
    const element = triggerElement || document.body;

    const preloadOnce = () => {
      this.preload(componentName, importFn);
      element.removeEventListener('mouseover', preloadOnce);
      element.removeEventListener('touchstart', preloadOnce);
    };

    element.addEventListener('mouseover', preloadOnce, { once: true });
    element.addEventListener('touchstart', preloadOnce, { once: true });
  }
}

export const preloadManager = new PreloadManager();

// 图片懒加载 Hook
export function useImageLazyLoading(
  src: string,
  options: IntersectionObserverInit = {}
) {
  const [imageSrc, setImageSrc] = React.useState<string>('');
  const [imageRef, setImageRef] = React.useState<HTMLImageElement | null>(null);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(false);

  React.useEffect(() => {
    if (!imageRef) return;

    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setImageSrc(src);
          observer.unobserve(entry.target);
        }
      },
      {
        rootMargin: '50px',
        ...options,
      }
    );

    observer.observe(imageRef);

    return () => {
      if (imageRef) {
        observer.unobserve(imageRef);
      }
    };
  }, [imageRef, src, options]);

  const handleLoad = () => {
    setLoading(false);
    setError(false);
  };

  const handleError = () => {
    setLoading(false);
    setError(true);
  };

  return {
    imageRef: setImageRef,
    imageSrc,
    loading,
    error,
    handleLoad,
    handleError,
  };
}

// 导出所有工具
export {
  PageLoading,
  CardLoading,
  TableLoading,
  SkeletonLoader,
};